package com.sixnimmt.app.client.game.view;

import java.util.HashMap;
import java.util.Map;

import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sixnimmt.app.client.Constants;
import com.sixnimmt.app.client.game.presenter.GamePresenter;
import com.sixnimmt.app.client.game.view.dialog.ScoreDialog;
import com.sixnimmt.app.client.game.view.panel.HorizontalPlayerPanel;
import com.sixnimmt.app.client.game.view.panel.PlayerHandCardsPanel;
import com.sixnimmt.app.client.game.view.panel.PlayerPanel;
import com.sixnimmt.app.client.game.view.panel.VerticalPlayerPanel;
import com.sixnimmt.app.client.i18n.SixNimmtMessages;
import com.sixnimmt.app.shared.game.domain.Board;

public class GameView extends Composite implements GamePresenter.Display {

	private final SixNimmtMessages messages;
	private final Map<String, PlayerPanel> playersArea = new HashMap<String, PlayerPanel>();
	private final HorizontalPanel northPlayersPanel;
	private final VerticalPanel eastPlayersPanel;
	private final VerticalPanel westPlayersPanel;
	private final HorizontalPanel playerZonePanel;
	private final Grid stacksPanel;
	private final Button startButton;
	private final Button restartButton;
	private final PlayerHandCardsPanel playerHandCardsPanel;
	private final ScoreDialog scoreDialog;

	public GameView(SixNimmtMessages messages) {
		this.messages = messages;

		DockLayoutPanel dockLayoutPanel = new DockLayoutPanel(Unit.EM);
		initWidget(dockLayoutPanel);
		dockLayoutPanel.setStyleName("board");

		FlowPanel northPanel = new FlowPanel();
		dockLayoutPanel.addNorth(northPanel, 10);

		northPlayersPanel = new HorizontalPanel();
		northPanel.add(northPlayersPanel);

		FlowPanel eastPanel = new FlowPanel();
		dockLayoutPanel.addEast(eastPanel, 10);

		eastPlayersPanel = new VerticalPanel();
		eastPanel.add(eastPlayersPanel);

		startButton = new Button(messages.startGame());
		startButton.setStyleName("invisible");
		eastPlayersPanel.add(startButton);

		restartButton = new Button(messages.restartServer());
		restartButton.setStyleName("invisible");
		eastPlayersPanel.add(restartButton);

		FlowPanel westPanel = new FlowPanel();
		dockLayoutPanel.addWest(westPanel, 10);

		westPlayersPanel = new VerticalPanel();
		westPanel.add(westPlayersPanel);

		FlowPanel southPanel = new FlowPanel();
		dockLayoutPanel.addSouth(southPanel, 11);

		playerZonePanel = new HorizontalPanel();
		playerZonePanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_BOTTOM);
		southPanel.add(playerZonePanel);

		playerHandCardsPanel = new PlayerHandCardsPanel();
		playerZonePanel.add(playerHandCardsPanel);

		stacksPanel = new Grid(Board.STACK_NUMBER, Board.STACK_MAX_SIZE + 1);
		stacksPanel.setStyleName("stacks");
		dockLayoutPanel.add(stacksPanel);
		stacksPanel.getElement().getStyle().setPosition(Position.RELATIVE);

		for (int i = 0; i < Board.STACK_NUMBER; i++) {
			final Image stackIdentifier = new Image("images/cards/arrow.png");
			stackIdentifier.setHeight(Constants.ARROW_HEIGHT + "px");
			stackIdentifier.setWidth(Constants.ARROW_WIDTH + "px");
			stackIdentifier.setAltText("> " + (i + 1));
			stackIdentifier.setStyleName("cursor-hand");
			stackIdentifier.addStyleName("invisible");
			stacksPanel.setWidget(i, 0, stackIdentifier);
		}

		for (int i = 0; i < Board.STACK_NUMBER; i++) {
			for (int j = 0; j < Board.STACK_MAX_SIZE; j++) {
				final AbsolutePanel cardPlace = new AbsolutePanel();
				cardPlace.setStyleName("card-place");
				stacksPanel.setWidget(i, j + 1, cardPlace);
			}
		}

		scoreDialog = new ScoreDialog(messages);

	}

	@Override
	public Widget asWidget() {
		return this;
	}

	@Override
	public void addOpponentArea(String playerName) {
		if (playersArea.size() < 5) {
			PlayerPanel playerArea = new VerticalPlayerPanel(messages, playerName);
			westPlayersPanel.add(playerArea);
			playersArea.put(playerName, playerArea);
		} else {
			PlayerPanel playerArea = new HorizontalPlayerPanel(messages, playerName);
			northPlayersPanel.add(playerArea);
			playersArea.put(playerName, playerArea);
		}
	}

	@Override
	public void initMyArea(String myName) {
		PlayerPanel currentPlayerPanel = new VerticalPlayerPanel(messages, myName);
		playerZonePanel.insert(currentPlayerPanel, 0);
		playersArea.put(myName, currentPlayerPanel);
	}

	@Override
	public HasText getPlayerScore(String playerName) {
		return playersArea.get(playerName).playerScore;
	}

	@Override
	public HasText getPlayerTakenCards(String playerName) {
		return playersArea.get(playerName).takenCards;
	}

	@Override
	public Panel getPlayerPlayedCardLocation(String playerName) {
		return playersArea.get(playerName).choosenCard;
	}

	@Override
	public Panel getCurrentPlayerHand() {
		return playerHandCardsPanel;
	}

	@Override
	public Panel getCardLocation(int stack, int position) {
		return (Panel) stacksPanel.getWidget(stack, position + 1);
	}

	@Override
	public HasClickHandlers getStartButton() {
		return startButton;
	}

	@Override
	public HasClickHandlers getRestartServerButton() {
		return restartButton;
	}

	@Override
	public HasClickHandlers[] getStackIdentifiers() {
		HasClickHandlers[] result = new HasClickHandlers[Board.STACK_NUMBER];
		for (int i = 0; i < result.length; i++) {
			result[i] = (HasClickHandlers) stacksPanel.getWidget(i, 0);
		}
		return result;
	}

	@Override
	public ScoreDialog getScoreDialog() {
		return scoreDialog;
	}

}
